<?php
namespace app\qsapi\service;

use app\common\controller\Notice;
use app\common\controller\Sms;
use app\qsapi\model\BoxHotAvatar;
use app\qsapi\model\BoxMemberChangeLog;
use app\qsapi\model\BoxMemberInfo;
use app\qsapi\model\BoxMemberLike;
use app\qsapi\model\BoxNotice;
use app\qsapi\model\BoxResourceMyservice;
use app\qsapi\model\Member;
use app\qsapi\model\MemberAuth;
use app\qsapi\model\MemberLogOff;
use think\cache\driver\Redis;
use think\Db;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\exception\DbException;
use think\facade\Env;

use TencentCloud\Common\CommonClient;
use TencentCloud\Common\Exception\TencentCloudSDKException;
use TencentCloud\Common\Credential;
use TencentCloud\Common\Profile\ClientProfile;
use TencentCloud\Common\Profile\HttpProfile;


class MemberService extends BaseService
{

    /**
     * 用户id
     * @param $member_id
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getInfo($member_id): array
    {
        $member = new Member();
        $info = $member->getInfoByWhere(['id' => $member_id, 'mark' => 1], 'id,username,phone,nickname,avatar,age_status,create_time,source');
        if (!$info) {
            return [];
        }
        $memberInfoModel = new BoxMemberInfo();
        $member_info = $memberInfoModel->getInfoByWhere(['member_id' => $member_id], 'member_id,follow,fans,collect,svip,intro,sex,birthday,is_push_notice,ban_rule,ban_time,ban_began_time,adolescent,score,vip_growth');

        //获取未读消息数
        $param = [
            'type' => 2
        ];
        $result = $this->noticeList($member_id, $param);
        if (!empty($result)) {
            $info['unread'] = $result['data']['total'] ?? 0;
        } else {
            $info['unread'] = 0;
        }

        if ($info['unread']) {
            $info['notify_true'] = true;
        } else {
            $info['notify_true'] = false;
        }

        $info['birthday'] = empty($info['birthday']) ? '' : $info['birthday'];
        $info['avatar'] = imageUrl($info['avatar']) ?? '';
        $info['disappear'] = (new MemberLogOff())->where('member_id', $member_id)->where('status', 1)->find() ? 1 : 0;
        $info['examine_avatar'] = (new  BoxMemberChangeLog())->field('new_value')->where('member_id', $member_id)->where('type_name', 'avatar')
            ->where('status', 0)->order('create_time desc')->select();
        //添加身份证信息
        $certified = $this->certified($member_id);
        $info['realname'] = $certified['data']['realname'] ?? '';
        $info['idcard'] = $certified['data']['idcard'] ?? '';

        return array_merge(is_array($info) ? $info : $info->toArray(), is_array($member_info) ? $member_info : $member_info->toArray());
    }

    /**
     * Notes: 修改用户信息
     * User: liubaoqiang
     * DateTime: 2024/12/4 13:43
     * @param $member_id
     * @param $param
     * @return array
     */
    public function saveInfo($member_id, $param): array
    {
        Db::startTrans();
        try {
            $member_save = [];
            $changeModel = new BoxMemberChangeLog();
            $member = new Member();
            $memberInfoModel = new BoxMemberInfo();
            $info = $member->getInfoByWhere(['id' => $member_id]);
            $member_info = $memberInfoModel->getInfoByWhere(['member_id' => $member_id]);
            if (!empty($param['username'])) {
//                $sensitive = self::checkSensitive($param['username'], $member_id);
//                if ($sensitive) {
//                    return api_message([], '修改用户名请规避敏感词汇', 0);
//                }
                //判断本月是否修改过
                if ($changeModel->where('member_id', $member_id)->where('type_name', 'username')->where('create_time', '>=', strtotime(date('Y-m-01')))
                    ->where('create_time', '<=', strtotime(date('Y-m-t 23:59:59')))->find()
                ) {
                    return api_message([], '用户名每个自然月仅允许修改一次', 0);
                }
                if ($info['username'] == $param['username']) {
                    return api_message([], '请修改用户名后提交', 0);
                }
                $member_save['username'] = $param['username'];
            }
            if (!empty($param['nickname'])) {
//                $sensitive = self::checkSensitive($param['nickname'], $member_id);
//                if ($sensitive) {
//                    return api_message([], '修改昵称请规避敏感词汇', 0);
//                }
                //判断本月是否修改过
                if ($changeModel->where('member_id', $member_id)->where('type_name', 'nickname')->where('create_time', '>=', strtotime(date('Y-m-01')))
                    ->where('create_time', '<=', strtotime(date('Y-m-t 23:59:59')))->find()
                ) {
                    return api_message([], '昵称每个自然月仅允许修改一次', 0);
                }
                if ($info['nickname'] == $param['nickname']) {
                    return api_message([], '请修改昵称后提交', 0);
                }
                $member_save['nickname'] = $param['nickname'];
            }
            if (!empty($param['avatar'])) {
                //判断是否有在审核中的头像
                $changeResult = $changeModel->where('member_id', $member_id)->where('type_name', 'avatar')->where('status', '=', 0)->find();
                if ($changeResult) {
                    return api_message([], '有在审核中的头像', 0);
                }
                $this->createChangeLog($member_id, 'avatar', $info['avatar'], $param['avatar'], 0);
            }
            if ($member_save) {
                $member_save['update_time'] = time();
                $member->updateRow(['id' => $member_id], $member_save);
                if (isset($member_save['username'])) {
                    $this->createChangeLog($member_id, 'username', $info['username'], $member_save['username'], 1);

                }
                if (isset($member_save['nickname'])) {
                    $this->createChangeLog($member_id, 'nickname', $info['nickname'], $member_save['nickname'], 1);
                }
            }
            $member_info_save = [];
            if (isset($param['intro']) && $param['intro']) {
//                $sensitive = self::checkSensitive($param['intro'], $member_id);
//                if ($sensitive) {
//                    return api_message([], '修改签名请规避敏感词汇', 0);
//                }
                if ($changeModel->where('member_id', $member_id)->where('type_name', 'intro')->where('create_time', '>=', strtotime(date('Y-m-01')))
                    ->where('create_time', '<=', strtotime(date('Y-m-t 23:59:59')))->find()
                ) {
                    return api_message([], '签名每个自然月仅允许修改一次', 0);
                }
                if ($member_info['intro'] == $param['intro']) {
                    return api_message([], '请修改签名后提交', 0);
                }
                $member_info_save['intro'] = $param['intro'];
            }
            if (isset($param['sex']) && $param['sex']) {
                $member_info_save['sex'] = $param['sex'];
            }
            if (isset($param['birthday']) && $param['birthday']) {
                $member_info_save['birthday'] = $param['birthday'];
            }
            if ($member_info_save) {
                $member_info_save['update_time'] = time();
                $memberInfoModel->updateRow(['member_id' => $member_id], $member_info_save);
                if (isset($member_info_save['intro'])) {
                    $this->createChangeLog($member_id, 'intro', $member_info['intro'], $member_info_save['intro'], 1);
                }
            }
            Db::commit();
            return api_message();
        } catch (Exception $e) {
            Db::rollback();
            return api_message([], $e->getMessage(), 0);
        }
    }


    /**、
     * 插入用户信息更改记录
     * @param $member_id 用户id
     * @param $type   提交类型
     * @param $oldValue  旧值
     * @param $newValue  新值
     * @param $status   审核状态 0 待审核  1 审核通过
     * @return true
     */
    public function createChangeLog($member_id, $type_string, $oldValue, $newValue, $status = 0)
    {
        $changeModel = new BoxMemberChangeLog();
        $changeModel->insertRow([
            'member_id'   => $member_id,
            'type_name'   => $type_string,
            'old_value'   => $oldValue,
            'new_value'   => $newValue,
            'status'      => $status,
            'create_time' => time(),
            'update_time' => time()
        ]);
        return true;
    }


    /**
     * 初始化用户额外信息
     * @param $member_id
     * @return array
     */
    public function initMemberInfo($member_id): array
    {
        $data['member_id'] = $member_id;
        $data['follow'] = 0;
        $data['fans'] = 0;
        $data['collect'] = 0;
        $data['svip'] = 0;
        $data['sex'] = 0;
        $data['intro'] = '';
        $data['birthday'] = null;
        $data['is_push_notice'] = 1;
        $data['ban_rule'] = '';
        $data['ban_time'] = 0;
        $data['ban_began_time'] = 0;
        $data['adolescent'] = 0;
        $data['create_time'] = time(); //注册时间
        $memberInfoModel = new BoxMemberInfo();
        $memberInfoModel->insert($data, true);
        return $data;
    }


    /**
     * 获取系统头像
     * @return array
     */
    public function getHotAvatar(): array
    {
        $hotKeysModel = new BoxHotAvatar();
        $where[] = ['mark', '=', 1];
        $where[] = ['status', '=', 1];
        $list = $hotKeysModel->field('id,name,desc,icon')->where($where)->order('sort desc')->select();
        if (!$list) return api_message($list);
        $list = $list->toArray();
        foreach ($list as $k => $item) {
            $list[$k]['icon'] = imageUrl($item['icon']);
        }
        return api_message($list);
    }


    /**
     * 更换绑定手机号
     * @param $member_id
     * @param $data
     * @return array
     */
    public function saveBindPhone($member_id, $data)
    {
        if (!isset($data['phone']) || !$data['phone'] || !isset($data['code']) || !$data['code']) {
            return api_message([], '请输入手机或者验证码', 0);
        }
        //校验验证码
        $sms = new Sms();
        $res = $sms->smsVerify($data['phone'], $data['code']);
        if (!isset($res['code']) || $res['code'] != 0) {
            return api_message([], $res['msg'] ?? '验证码错误', 1);
        }
        $memberModel = new Member();
        $member_info = $memberModel->where('id', $member_id)->find();
        if (!$member_info) {
            return api_message([], '用户不存在', 0);
        }
        if ($member_info['phone'] == $data['phone']) {
            return api_message([], '新手机号与旧手机号一致', 0);
        }
        //检查手机号是否被绑定
        $info = $memberModel->where('phone', $data['phone'])->whereNotIn('id', [$member_id])->find();
        if ($info) {
            return api_message([], '当前手机号已被绑定', 0);
        }
        //兼容sdk更换手机号   修改昵称也是手机号的
        $update['phone'] = $data['phone'];
        $update['update_time'] = time();
        if ($member_info['username'] == $member_info['phone']) {
            $update['username'] = $data['phone'];
        }
        $memberModel->updateRow(['id' => $member_id], $update);
        //添加一个换绑日志
        (new BoxChangeBindingPhoneLog)->insertRow([
            'member_id' => $member_id,
            'new_phone' => $data['phone'],
            'old_phone' => $member_info['phone'] ?? '',
        ]);
        return api_message();
    }


    /**
     * 实名认证
     * @param $member_id
     * @param $data
     * @return array
     */
    public function realAuth($member_id, $data): array
    {
        if (!isset($data['real_name']) || !$data['real_name'] || !isset($data['id_card']) || !$data['id_card']) {
            return api_message([], '请输入姓名和身份号', 0);
        }
        $postData = array(
            'Name' => $data['real_name'],
            'IdCard'   => $data['id_card']
        );

        try {
            $cred = new Credential(config('idCard.secretId'), config('idCard.secretKey'));
            $httpProfile = new HttpProfile();
            $httpProfile->setEndpoint(config('idCard.url'));
            $clientProfile = new ClientProfile();
            $clientProfile->setHttpProfile($httpProfile);
            $client = new CommonClient("faceid", "2018-03-01", $cred, "", $clientProfile);
            $postData = json_encode($postData);
            $resp = $client->callJson("IdCardVerification", json_decode($postData));
            $idCardResult =  json_encode($resp);
        }catch (TencentCloudSDKException $e){
            return api_message([], $e);
        }

        $idCardResult = json_decode($idCardResult);
        //插入实名认证记录
        $memberAuthModel = new MemberAuth();
        $memberAuthData['uid'] = $member_id;
        $memberAuthData['idcard'] = encrypt($data['id_card'], config('api.CRYPTKEY'));
        $memberAuthData['realname'] = encrypt($data['real_name'], config('api.CRYPTKEY'));
        $memberAuthData['create_time'] = now();
        if (isset($idCardResult) && $idCardResult->Result == 0) {
            $save['idcard'] = $memberAuthData['idcard'];
            $save['realname'] = $memberAuthData['realname'];
            $save['age_status'] = 1;
            $save['update_time'] = time();
            $memberModel = new Member();
            $memberModel->updateRow(['id' => $member_id], $save);
            $memberAuthData['status'] = 1;
            $memberAuthData['reason'] = '认证成功';
            $memberAuthModel->insertRow($memberAuthData);
            return api_message([], '认证成功');
        } else {
            $memberAuthData['status'] = 0;
            $memberAuthData['reason'] = ($idCardResult->Description ?? '认证失败');
            $memberAuthModel->insertRow($memberAuthData);
            return api_message([], ($idCardResult->Description ?? '认证失败'), 0);
        }
    }

    /**
     * 获取姓名 身份证号
     * @param $member_id
     * @return array
     */
    public function certified($member_id): array
    {
        $memberModel = new Member();
        $member_info = $memberModel->where('id', $member_id)->find();
        if (!$member_info) {
            return api_message([], '用户不存在', 0);
        }
        $data['age_status'] = $member_info['age_status'];
        $data['realname'] = $data['idcard'] = '';
        if ($data['age_status'] > 0) {
            $data['realname'] = starReplace(decrypt($member_info['realname'], config('api.CRYPTKEY')), 1);
            $data['idcard'] = hide_id_number(decrypt($member_info['idcard'], config('api.CRYPTKEY')));

        }
        return api_message($data);
    }

    /**
     * 消息推送
     * @param $member_id
     * @param $data
     * @return array
     */
    public function pushNotice($member_id, $data): array
    {
        if (!isset($data['is_push'])) {
            return api_message([], '请输入参数', 0);
        }
        if (!in_array($data['is_push'], [0, 1])) {
            return api_message([], '参数错误', 0);
        }
        $memberModel = new BoxMemberInfo();

        $memberModel->updateRow(['member_id' => $member_id], ['update_time' => time(), 'is_push_notice' => $data['is_push'] ?? 0, 'is_push_notice_time' => time()]);
        //todo  增加开关记录表
        return api_message();
    }

    /**
     * 手机号验证码登录
     * @param $data
     * @return array
     */
    public function disappearAccount($member_id, $data)
    {
        if (!isset($data['code']) || !$data['code']) {
            return api_message([], '请输入验证码', 0);
        }
        $info = (new Member())->getInfoByWhere(['id' => $member_id]);
        if (empty($info['phone'])) {
            return api_message([], '未绑定手机号，请先绑定手机号或者联系客服操作', 0);
        }
        $memberInfoModel = new MemberLogOff();
        //判断是否在注销期间
        $log_info = (new MemberLogOff())->getInfoByWhere(['member_id' => $member_id, 'status' => 1]);
        if ($log_info) {
            return api_message([], '您已提交注销', 0);
        }
        //校验验证码
        $sms = new Sms();
        $res = $sms->smsVerify($info['phone'], $data['code']);
        if (!isset($res['code']) || $res['code'] != 0) {
            return api_message([], $res['msg'] ?? '验证码错误', 1);
        }
        $insert_data['member_id'] = $member_id;
        $insert_data['member_account'] = $info['username'];
        $insert_data['add_time'] = time();
        $insert_data['status'] = 1;
        $insert_data['type'] = 2;
        $memberInfoModel->insertRow($insert_data);
        return api_message();
    }

    /**
     * 取消注销账号
     * @param $member_id
     * @return array
     * @throws \Exception
     */
    public function canalDisappearAccount($member_id)
    {
        $memberInfoModel = new MemberLogOff();
        $memberInfoModel->where('member_id', $member_id)->where('status', 1)->update(['status' => 3]);
        return api_message();
    }


    /**
     * 消息列表
     * @param $member_id
     * @param $param
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function noticeList($member_id, $param): array
    {
        $limit = $param['limit'] ?? 10;
        $type = $param['type'] ?? 0;
        $model = new BoxNotice();
        $member = (new Member())->where('id', $member_id)->find()->toArray();
        $list = $model->field('id,member_id,title,content,source,read_time,create_time,system_id,extend_id')->order('create_time desc');
        $list = $list->where('create_time', '>=', $member['create_time']);

        $pushNotice = (new BoxMemberInfo())->field('is_push_notice,is_push_notice_time')->where('member_id', $member_id)->find();
        $notice_off_time = 0;
        if (!empty($pushNotice) && $pushNotice['is_push_notice'] == 0) {
            $notice_off_time = $pushNotice['is_push_notice_time'] ?? 0;
        }

        if ($type == 1) {//已读
            $list = $list->where('member_id', $member_id)->where('read_time', '>', 0);
        } else if ($type == 2) {  //未读
            //获取已读的系统消息
            $ids = $model->where('member_id', $member_id)->where('system_id', '>', 0)->column('system_id');
            $list = $list->where('member_id = -1 OR member_id = ' . $member_id)
                ->whereNotIn('id', $ids)
                ->where('read_time', '=', 0);
            if (!empty($notice_off_time)) {
                $list = $list->where('create_time', '<', $notice_off_time);
            }
        } else { //全部
            $list = $list->where('member_id = -1 OR member_id = ' . $member_id)->where('system_id', 0);
            if (!empty($notice_off_time)) {
                $list = $list->where('create_time', '<', $notice_off_time);
            }
        }
        $list = $list->paginate($limit)->toArray();
        $data['list'] = [];
        $data['total'] = 0;
        if ($list['total'] <= 0) {
            return api_message($data);
        }
        //获取帖子评论的额外信息
        $comment_ids = $comment_list = $beLikeList = [];
        foreach ($list['data'] as $item) {
            if ($item['source'] == 2) {
                $comment_ids[] = $item['extend_id'];
            }
        }

        if ($comment_ids) {
            //获取评论信息
            $comment_list = Db::name('box_article_comment')->alias('a')
                ->field('a.id,b.title,a.create_user,c.nickname, c.avatar,FROM_UNIXTIME(a.create_time) AS comment_time')
                ->leftJoin('box_article b', 'a.box_article_id=b.id')
                ->leftJoin('member c', 'a.create_user=c.id')
                ->whereIn('a.id', $comment_ids)->select();
            $comment_list = array_column($comment_list, null, 'id');
            $to_member_ids = array_column($comment_list ?? [], 'create_user');
            if ($to_member_ids) {
                $beLikeList = (new BoxMemberLike())->where('member_id', $member_id)->whereIn('to_member_id', $to_member_ids)->where('status', 1)->select();
                $beLikeList = array_column($beLikeList ? $beLikeList->toArray() : [], null, 'to_member_id');
            }
        }
        //获取对应的帖子评论
        foreach ($list['data'] as $k => $item) {
            $list['data'][$k]['content'] = str_replace("\n", "", mb_substr($item['content'], 0, 40)) . '...';
            $list['data'][$k]['create_time'] = date('Y-m-d H:i:s', $item['create_time']);
            //查找当前消息有没有被用户读取
            $result = $model->field('read_time')->where(['system_id' => $item['id'], 'member_id' => $member_id])->find();
            if ($item['member_id'] == -1 && !empty($result)) {
                $list['data'][$k]['read_time'] = $result['read_time'];
            }
            $list['data'][$k]['comment_info'] = [];
            if ($item['source'] == 2 && isset($comment_list[$item['extend_id']])) {
                $comment_list[$item['extend_id']]['is_like'] = isset($beLikeList[$comment_list[$item['extend_id']]['create_user']]) ? 1 : 0;
                $list['data'][$k]['comment_info'] = $comment_list[$item['extend_id']];
            }
        }

        $data['list'] = $list['data'];
        $data['total'] = $list['total'];
        return api_message($data);
    }

    /**
     * 消息内容
     * @param $member_id
     * @param $id
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function noticeInfo($member_id, $id): array
    {

        $model = new BoxNotice();
        $where[] = ['id', '=', $id];
        // $where[] = ['member_id', '=', $member_id];
        $info = $model->where($where)->field('id,member_id,title,content,source,read_time,create_time,extend_id')->find();

        if (empty($info)) {
            return api_message([], '消息不存在', 0);
        }
        if ($info['member_id'] != -1 && $info['member_id'] != $member_id) {
            return api_message([], '消息错误', 0);
        }

        if ($info['member_id'] == -1) {
            //系统消息  读取的时候 才插入用户读取记录
            $system_info = $model->where('member_id', $member_id)->where('system_id', $id)->find();
            if (!$system_info) {
                $model->insertRow([
                    'member_id'   => $member_id,
                    'title'       => $info['title'] ?? '',
                    'content'     => $info['content'] ?? '',
                    'source'      => $info['source'] ?? '',
                    'read_time'   => time(),
                    'create_time' => $info['create_time'] ?? 0,
                    'update_time' => time(),
                    'system_id'   => $info['id'] ?? 0
                ]);
            }
        } else {
            if ($info['read_time'] == 0) {
                $model->where($where)->update(['read_time' => time(), 'update_time' => time()]);
            }
        }
        $info['create_time'] = date('Y-m-d H:i:s', $info['create_time']);
        $info['comment_info'] = [];
        if ($info['source'] == 2) {//如果是评论消息  增加额外扩展字段
            $comment_info = Db::name('box_article_comment')->alias('a')
                ->field('a.id,b.title,a.create_user,c.nickname, c.avatar, FROM_UNIXTIME(a.create_time) AS comment_time')
                ->leftJoin('box_article b', 'a.box_article_id=b.id')
                ->leftJoin('member c', 'a.create_user=c.id')
                ->where('a.id', $info['extend_id'])->find();
            if ($comment_info) {
                $comment_info['is_like'] = (new BoxMemberLike())->where('member_id', $member_id)->where('to_member_id', $comment_info['create_user'])
                    ->where('status', 1)->find() ? 1 : 0;
                $info['comment_info'] = $comment_info;
            }
        }
        $info = $info->toArray();
        //同步redis
        (new  Notice($member_id))->read($info);
        return api_message($info);
    }

    /**
     * Desc : 我的服务配置
     * User : you name
     * Date : 2024-01-13 14:36
     */
    public function getMyServiceConfig($params): array
    {
        $version = intval(implode('', explode('.', $params)));
        $platform = strtolower($this->platform) ?? '';
        $redis = new Redis(getRedisConfig());
        $list = $redis->get('BOX_RESOURCE_MYSERVICE' . $platform);
        $list = $list ? json_decode($list, true) : [];
        if (!$list) {
            $model = new BoxResourceMyservice();
            $where[] = ['status', '=', 1];
            $where[] = ['mark', '=', 1];
            if (!empty($params)) {
                $where[] = ['version', '<=', $version];
            }
            $list = $model->field('id,title,icon,select_icon,link,sort,version')->where($where);
            $list = $list->order('sort desc')->select();
            $list = $list ? $list->toArray() : [];
            if (!$list) {
                return message('获取失败', false);
            }
            foreach ($list as $k => $item) {
                $list[$k]['icon'] = imageUrl($item['icon']);

            }
            $redis->set('BOX_RESOURCE_MYSERVICE' . $platform, json_encode($list), 5);
        }
        return api_message($list, '获取成功');
    }
}
